#ifndef _SERVICE_H
#define	_SERVICE_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <malloc.h>
#include <unistd.h>

#define D(x) x
//#define DEBUG
#define MOD_ADLER 65521
#define PROHIBITED_NAMES_QUANTITY 22
#define MAX_FILENAME_LENGTH 256

typedef struct ArchObj {
    unsigned char name[MAX_FILENAME_LENGTH];
    size_t offset, absolute_offset;
    unsigned long hash;
    struct ArchObj *right, *left;
} arfile;

typedef struct Huffmam_Tree {
    unsigned char data;
    unsigned long long int weight;
    struct Huffmam_Tree *right, *left;
} node;

typedef struct List {
    node *tree;
    struct List *next, *prev;
} list;

inline FILE *openFileRB(unsigned char* name);
inline FILE *openFileWB(unsigned char *name);
inline long long encode_to_file(unsigned char bit[], FILE *out, int mode, int reset);
inline unsigned char count_symbols(unsigned long *array);
inline void decode_to_file(node *root, FILE *in, unsigned long long int num_of_symbols, FILE *out);
inline void print_binary(unsigned char var);
int addToArfileTree(arfile **root, arfile *in_node);
int analyse_command_line_arc_mode(unsigned char input[]);
int append_files(int count, unsigned char *args[]);
int buildArfileList(FILE *f, arfile **root);
int build_tree(node **root, unsigned long sym_array[]);
int decodeAllFiles(FILE *f);
int decodeByOffset(FILE *f, size_t offset, int useTempDir);
int findFileInArchive(unsigned char* needle, arfile *root, size_t *absOffset, size_t *relOffset);
int main(int argc, char* argv[]);
int testIfRightArchiveFormat(FILE *f, unsigned char name[]);
int testIntegrity(FILE *f);
int validate_filename(unsigned char input[]);
node *get_from_list(list **head);
unsigned long adler32(FILE *f);
unsigned long long sym_freq(FILE *input, unsigned long sym_array[]);
void add_to_list(list **head, node *data);
void annihilate_arfiletree(arfile *root);
void annihilate_tree(node **root);
void build_table(node *root, unsigned char *entry, int length, unsigned char array[][256]);
void decodeByFilenames(FILE* f, unsigned char** argv, int argc);
void deleteByFilenames(FILE *f, unsigned char** argv, int argc);
void encode(FILE *f, unsigned long sym_array[], unsigned char table[][256], FILE *out);
void print_error(int error, unsigned char input[]);
void print_help_info();
void print_list(list *head);
void print_sym_freq_stat(unsigned char file_name[], unsigned long array[]);
void psgraph_tree_print(node *root, int offset);
void sel_sort(size_t *mainArray, size_t *subArray, int num);
void traverseArfileTree(arfile *root);
void tree_print(node *root);

enum {
    ARGS = 0, 
    FILENAME_INV_OR_NULL = -1,
    OPENING_FILE = -2,
    IGNORED_PARAMS = -3,
    NO_FILES = -4,
    NO_FREE_MEMORY = -5,
    INVALID_ARC_OR_DAMAGED = -6,
    CORRUPTED_FILE_IN_ARC = -7,
    UNKNOWN_PARAM = -8,
    NOTUNIQUE_NAME = -9,
    SUBTEST_FAIL = -10,
    FILE_NOT_FOUND = -11,
    OPENING_TEMP_FILE = -12,
    REMOVING_FILE = -13,
    MOVING_FILE = -14   
} ERROR_NUM;

enum {
    ERROR = 0, APPEND, EXTRACT, /*EXTRACT_REL,*/ DELETE, LIST, TEST/*, BLACKJACK*/
} command;

#endif	/* _SERVICE_H */

